home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Softice Tuts / si-ug-chapter12.rtf < prev    next >
Text File  |  2000-05-25  |  27KB  |  679 lines

  1.                                 We will now discuss in a little more detail
  2.                                                 the struggle for existence.
  3.                                                              Charles Darwin
  4.  
  5. SoftICE Tutorial
  6.  
  7.      Introduction
  8.      Loading SoftICE
  9.      Building the GDIDEMO Sample Application
  10.      Loading the GDIDEMO Sample Application
  11.      Controlling the SoftICE Screen
  12.      Tracing and Stepping through Source Code
  13.      Viewing Local Data
  14.      Setting Point-and-Shoot Breakpoints
  15.           Setting a One-Shot Breakpoint
  16.           Setting a Sticky Breakpoint
  17.      Using SoftICE Informational Commands
  18.      Using Symbols and Symbol Tables
  19.      Setting a Conditional Breakpoint
  20.           Setting a BPX Breakpoint
  21.           Editing a Breakpoint
  22.      Setting a Read-Write Memory Breakpoint
  23.  
  24. Introduction
  25.  
  26.      This tutorial gives you hands-on experience debugging a Windows
  27.      application to teach you the fundamental steps for debugging
  28.      applications and drivers. During this debugging session, you will
  29.      learn how to do the following:
  30.  
  31.    * Load SoftICE
  32.    * Build an application
  33.    * Load the application source and symbol files
  34.    * Trace and step through source code and assembly language
  35.    * View local data and structures
  36.    * Set point-and-shoot breakpoints
  37.    * Use SoftICE informational commands to explore the state of the
  38.      application
  39.    * Work with symbols and symbol tables
  40.    * Modify a breakpoint to use a conditional expression
  41.  
  42.      Each section in the tutorial builds upon the previous sections, so you
  43.      should perform them in order.
  44.  
  45.      This tutorial uses the GDIDEMO application as its basis. GDIDEMO
  46.      provides a demonstration of GDI functionality. GDIDEMO is located in
  47.      the \EXAMPLES\GDIDEMO directory on your CDROM. GDIDEMO is also
  48.      available under \mstools\samples\win32\GDIDEMO. If you use the GDIDEMO
  49.      on the CDROM, copy it to your hard drive.
  50.  
  51.      You can substitute a different sample application or an application of
  52.      your own design. The debugging principles and features of SoftICE used
  53.      in this tutorial apply to most applications.
  54.  
  55.      Note: The examples is this tutorial are based on Windows NT. If you
  56.      are using Windows 95, your output may vary slightly.
  57.  
  58. Loading SoftICE
  59.  
  60.      If you are running SoftICE under Windows 95 or under Windows NT in
  61.      Boot, System, or Automatic mode, SoftICE automatically loads when you
  62.      start or reboot your PC. If you are running SoftICE in Manual Startup
  63.      mode under Windows NT, SoftICE does not load automatically.
  64.  
  65.      To load SoftICE for Windows 95, enter the command WINICE. To load
  66.      SoftICE for Windows NT, do one of the following:
  67.  
  68.    * Select START SOFTICE.
  69.    * Enter the command: NET START NTICE
  70.  
  71.      Note: Once you load SoftICE, you cannot deactivate it until you reboot
  72.      your PC.
  73.  
  74.      To verify that SoftICE is loaded, press the SoftICE hot key sequence
  75.      Ctrl-D. The SoftICE screen should appear. To return to the Windows
  76.      operating system, use the X (exit) or G (go to) command (F5).
  77.  
  78. Building the GDIDEMO Sample Application
  79.  
  80.      The first step in preparing to debug a Windows application is to build
  81.      it with debug information. The makefile for the sample application
  82.      GDIDEMO is already set up for this purpose.
  83.  
  84.      To build the sample program, perform the following steps:
  85.  
  86.      1. Open a DOS shell.
  87.  
  88.      2. Change to the directory that contains the sample code.
  89.  
  90.      3. Execute the NMAKE command:
  91.  
  92.      C:\MSTOOLS\SAMPLES\WIN32\GDIDEMO>NMAKE
  93.  
  94.      If GDIDEMO is located in another directory, change the path as
  95.      appropriate.
  96.  
  97. Loading the GDIDEMO Sample Application
  98.  
  99.      Loading an application entails creating a symbol file from the
  100.      applicationÆs debug information and loading the symbol and source
  101.      files into SoftICE. To Load the GDIDEMO application, perform the
  102.      following steps:
  103.  
  104.      1. Start Symbol Loader : The Symbol Loader window appears.
  105.  
  106.      2. Either choose OPEN MODULE from the File menu or click the OPEN
  107.      button : The Open window appears.
  108.  
  109.      3. Locate GDIDEMO.EXE and click Open.
  110.  
  111.      4. Either choose LOAD from the Module menu or click the LOAD button to
  112.      load GDIDEMO.
  113.  
  114.      Symbol Loader translates the debug information into a .NMS symbol
  115.      file, loads the symbol and source files, starts GDIDEMO, pops up the
  116.      SoftICE screen, and displays the source code for the file GDIDEMO.C.
  117.  
  118. Controlling the SoftICE Screen
  119.  
  120.      The SoftICE screen is your central location for viewing and debugging
  121.      code. It provides up to seven windows and one help line to let you
  122.      view and control various aspects of your debugging session. By
  123.      default, it displays the following:
  124.  
  125.      Locals window: Displays and expand variables allocated on the stack.
  126.  
  127.      Code window: Displays source code or unassembled instructions.
  128.  
  129.      Command window: Enters user commands and display information.
  130.  
  131.      Help line: Provides information about SoftICE commands and shows the
  132.      active address context.
  133.  
  134.      1. Look at the contents of the Code window. Note that SoftICE is
  135.      displaying the WinMain routine at line 34. By default, SoftICE creates
  136.      a breakpoint and stops at the first main module it encounters when
  137.      loading your application.
  138.  
  139.      2. To see all the source files that SoftICE loaded, enter the FILE
  140.      command with the wild card character:
  141.  
  142.      :FILE *
  143.  
  144.      SoftICE displays the source files for GDIDEMO: draw.c, maze.c,
  145.      xform.c, poly.c, wininfo.c, dialog.c, init.c, bounce.c, and gdidemo.c.
  146.      The Command window varies in size depending upon the number of lines
  147.      used by open windows, so you might not see all these file names. To
  148.      display the remaining file names, press any key. (Refer to Chapter 5:
  149.      Navigating Through SoftICE on page 69 for information about resizing
  150.      windows.)
  151.  
  152.      3. Many SoftICE windows can be scrolled. If you have a mouse, you can
  153.      click on the scroll arrows. If not, SoftICE provides key sequences
  154.      that let you scroll specific windows. Try these methods for scrolling
  155.      the Code window:
  156.  
  157.       Scroll the Code Window   Key Sequence    Mouse Action
  158.  
  159.       Scroll to the previous                   Click the innermost up
  160.       page.                    PageUp          scroll arrow
  161.  
  162.       Scroll to the next                       Click the innermost down
  163.       page.                    PageDown        scroll arrow
  164.  
  165.       Scroll to the previous                   Click the outermost up
  166.       line.                    UpArrow         scroll arrow
  167.  
  168.       Scroll to the next                       Click the outermost down
  169.       line.                    DownArrow       scroll arrow
  170.  
  171.       Scroll left one                          Click the left scroll
  172.       character.               Ctrl-LeftArrow  arrow
  173.  
  174.       Scroll right one                         Click the right scroll
  175.       character.               Ctrl-RightArrow arrow
  176.  
  177.      4. Enter the U command followed by EIP to disassemble the instructions
  178.      for the current instruction pointer.
  179.  
  180.      :U EIP
  181.  
  182.      You can also use the . (dot) command to accomplish the same thing:
  183.  
  184.      :.
  185.  
  186. Tracing and Stepping through Source Code
  187.  
  188.      The following steps show you how to use SoftICE to trace through
  189.      source code:
  190.  
  191.      1. Enter the T (trace) command or press the F8 key to trace one
  192.      instruction.
  193.  
  194.      :T
  195.  
  196.      The F8 key is the default key for the T (trace) command.
  197.  
  198.      Execution proceeds to the next source line and highlights it. At this
  199.      point, the following source line should be highlighted:
  200.  
  201.      if(!hPrevInst)
  202.  
  203.      2. The Code window is currently displaying source code. However, it
  204.      can also display disassembled code or mixed (both source and
  205.      disassembled) code. To view mixed code, use the SRC command (F3).
  206.  
  207.      :SRC
  208.  
  209.      Note that each source line is followed by its assembler instructions.
  210.  
  211.      3. Press F3 once to see disassembled code, then again to return to
  212.      source code.
  213.  
  214.      4. Enter the T command (F8) to trace one instruction. Execution
  215.      proceeds until it reaches the line that executes the RegisterAppClass
  216.      function.
  217.  
  218.      As demonstrated in these steps, the T command executes one source
  219.      statement or assembly language instruction. You can also use the P
  220.      command (F10) to execute one program step. Stepping differs from
  221.      tracing in one crucial way. If you are stepping and the statement or
  222.      instruction is a function call, control is not returned until the
  223.      function call is complete.
  224.  
  225.      Hint: The T command does not trace into a function call if the source
  226.      code is not available. A good example of this is Win32 API calls. To
  227.      trace into a function call when source code is not available, use the
  228.      SRC command (F3) to switch into mixed or assembly mode.
  229.  
  230. Viewing Local Data
  231.  
  232.      The Locals window displays the current stack frame. In this case, it
  233.      contains the local data for the WinMain function. The following steps
  234.      illustrate how to use the Locals window:
  235.  
  236.      1. Enter the T command to enter the RegisterAppClass function. The
  237.      Locals window is now empty because local data is not yet allocated for
  238.      the function.
  239.  
  240.      The RegisterAppClass function is implemented in the source file
  241.      INIT.C. SoftICE displays the current source file in the upper left
  242.      corner of the Code window.
  243.  
  244.      2. Enter the T command again. The Locals window contains the parameter
  245.      passed to the RegisterAppClass (hInstance) and a local structure
  246.      wndClass. The structure tag wndClass is marked with a plus sign (+).
  247.      This plus sign indicates that you can expand the structure to view its
  248.      contents.
  249.  
  250.      Note: You can also expand character strings and arrays.
  251.  
  252.      3. If you have a Pentium-class processor and a mouse, double-click the
  253.      structure WNDCLASSA to expand it. To collapse the structure wndClass,
  254.      double-click its contents.
  255.  
  256.      4. To use the keyboard to expand the structure: press Alt-L to move
  257.      the cursor to the Locals window, use the UpArrow or DownArrow to move
  258.      the highlight bar to the structure, and press Enter. Press Enter again
  259.      to collapse it.
  260.  
  261. Setting Point-and-Shoot Breakpoints
  262.  
  263.      This section shows you how to set two handy types of point-and-shoot
  264.      breakpoints: one-shot and sticky breakpoints.
  265.  
  266. Setting a One-Shot Breakpoint
  267.  
  268.      The following steps demonstrate how to set a one-shot breakpoint. A
  269.      one-shot breakpoint clears after the breakpoint is triggered.
  270.  
  271.      1. To shift focus to the Code window, either use your mouse to click
  272.      in the window or press Alt-C.
  273.  
  274.      If you wanted to shift focus back to the Command window you could
  275.      press Alt-C again. Setting Point-and-Shoot Breakpoints
  276.  
  277.      2. Either use the Down arrow key, the down scroll arrow, or the U
  278.      command to place the cursor on line 61, the first call to the Win32
  279.      API function RegisterClass. If you use the U command, specify the
  280.      source line 61 as follows:
  281.  
  282.      :U .61
  283.  
  284.      SoftICE places source line 61 at the top of the Code window.
  285.  
  286.      3. Use the HERE command (F7) to execute to line 61. The HERE command
  287.      executes from the current instruction to the instruction that contains
  288.      the cursor. The HERE command sets a one-shot breakpoint on the
  289.      specified address or source line and continues execution until that
  290.      breakpoint triggers. When the breakpoint is triggered, SoftICE
  291.      automatically clears the breakpoint so that it does not trigger again.
  292.  
  293.      The following current source line should be highlighted:
  294.  
  295.      if(!RegisterClass(&wndClass))
  296.  
  297.      Note: You can do the same thing by using the G (go) command and
  298.      specifying the line number or address to which to execute:
  299.  
  300.      :G .61
  301.  
  302. Setting a Sticky Breakpoint
  303.  
  304.      The following steps demonstrate another type of point-and-shoot
  305.      breakpoint: the sticky breakpoint, which does not clear until you
  306.      explicitly clear it.
  307.  
  308.      The F9 key is the default key for the BPX command.
  309.  
  310.      1. Find the next call to RegisterClass that appears on source line 74.
  311.      With the cursor on line 74, enter the BPX command (F9) to set an
  312.      execution breakpoint. The BPX command sets an execution breakpoint by
  313.      inserting an INT3 instruction into the code. Note that the line is
  314.      highlighted when you set a breakpoint.
  315.  
  316.      2. Press the F9 key to clear the breakpoint. If you are using a
  317.      Pentium-class processor and you have a mouse, you can double-click on
  318.      a line in the Code window to set or clear a breakpoint.
  319.  
  320.      3. Set a breakpoint on line 74, then use the G or X command (F5) to
  321.      execute the instructions until the breakpoint triggers:
  322.  
  323.      :G
  324.  
  325.      When the INT3 instruction is executed, SoftICE pops up. Unlike the
  326.      HERE command, which sets a one-shot breakpoint, the BPX command sets a
  327.      sticky breakpoint. A sticky breakpoint remains until you clear it.
  328.  
  329.      4. To view information about breakpoints that are currently set, use
  330.      the BL command:
  331.  
  332.      :BL
  333.      00) BPX #0137:00402442
  334.  
  335.      Note: The address you see might be different.
  336.  
  337.      From the output of the BL command, one breakpoint is set on code
  338.      address 0x402442. This address equates to source line 74 in the
  339.      current file INIT.C.
  340.  
  341.      5. You can use the SoftICE expression evaluator to translate a line
  342.      number into an address. To find the address for line 74, use the ?
  343.      command:
  344.  
  345.      :? .74
  346.      void * = 0x00402442
  347.  
  348.      6. The RegisterAppClass function has a relatively straightforward
  349.      implementation, so it is unnecessary to trace every single source
  350.      line. Use the P command with the RET parameter (F12) to return to the
  351.      point where this function was called:
  352.  
  353.      :P RET
  354.  
  355.      The RET parameter to the P command causes SoftICE to execute
  356.      instructions until the function call returns. Because RegisterAppClass
  357.      was called from within WinMain, SoftICE pops up in WinMain on the
  358.      statement after the RegisterAppClass function call.
  359.  
  360.      The following source line in WinMain should be highlighted:
  361.  
  362.      msg.wParam = 1;
  363.  
  364.      7. Enter the BC command with the wild card parameter to clear all the
  365.      breakpoints:
  366.  
  367.      BC *
  368.  
  369. Using SoftICE Informational Commands
  370.  
  371.      SoftICE provides a wide variety of informational commands that detail
  372.      the state of an application or the system. This section teaches you
  373.      about two of them: H (help) and CLASS.
  374.  
  375.      1. The H and Class commands work best when you have more room to
  376.      display information, so use the WL command to close the Locals window.
  377.      Closing this window automatically increases the size of the Command
  378.      window.
  379.  
  380.      2. The H command provides general help on all the SoftICE commands or
  381.      detailed help on a specific command. To view detailed help about the
  382.      CLASS command, enter CLASS as the parameter to the H command.
  383.  
  384.      :H CLASS
  385.      Display window class information
  386.      CLASS [-x] [process | thread | module | class-name]
  387.      ex: CLASS USER
  388.  
  389.      The first line of help provides a description of the command. The
  390.      second line is the detailed use, including any options and/or
  391.      parameters the command accepts. The third line is an example of the
  392.      command.
  393.  
  394.      3. The purpose of the RegisterAppClass function is to register window
  395.      class templates that are used by the GDIDEMO application to create
  396.      windows. Use the CLASS command to examine the classes registered by
  397.      GDIDEMO.
  398.  
  399.      :CLASS GDIDEMO
  400.  
  401.      Note: This example shows only those classes specifically registered by
  402.      the GDIDEMO application. Classes registered by other Windows modules,
  403.      such as USER32, are omitted.
  404.  
  405.      The output of the CLASS command provides summary information for each
  406.      window class registered on behalf of the GDIDEMO process. This
  407.      includes the class name, the address of the internal WINCLASS data
  408.      structure, the module which registered the class, the address of the
  409.      default window procedure for the class, and the value of the class
  410.      style flags.
  411.  
  412.      Note: For more specific information on window class definitions, use
  413.      the CLASS command with the -X option, as follows:
  414.  
  415.      :CLASS -X
  416.      Class Name  Handle    Owner    WndwProc  Styles
  417.      ---------------Application Private---------------
  418.      BOUNCEDEMO  A018A3B0  GDIDEMO  004015A4  00000003
  419.      DRAWDEMO    A018A318  GDIDEMO  00403CE4  00000003
  420.      MAZEDEMO    A018A280  GDIDEMO  00403A94  00000003
  421.      XFORMDEMO   A018A1E8  GDIDEMO  00403764  00000003
  422.      POLYDEMO    A018A150  GDIDEMO  00402F34  00000003
  423.      GDIDEMO     A018A0C0  GDIDEMO  004010B5  00000003
  424.  
  425. Using Symbols and Symbol Tables
  426.  
  427.      Now that you are familiar with using SoftICE to step, trace, and
  428.      create point-and-shoot style breakpoints, it is time to explore
  429.      symbols and tables. When you load symbols for an application, SoftICE
  430.      creates a symbol table that contains all the symbols defined for that
  431.      module.
  432.  
  433.      1. Use the TABLE command to see all the symbol tables that are loaded:
  434.  
  435.      :TABLE
  436.      GDIDEMO [NM32]
  437.      964657 Bytes Of Symbol Memory Available
  438.  
  439.      The currently active symbol table is listed in bold. This is the
  440.      symbol table used to resolve symbol names. If the current table is not
  441.      the table from which you want to reference symbols, use the TABLE
  442.      command and specify the name of the table to make active:
  443.  
  444.      :TABLE GDIDEMO
  445.  
  446.      2. Use the SYM command to display the symbols from the current symbol
  447.      table. With the current table set to GDIDEMO, the SYM command produces
  448.      output similar to the following abbreviated output:
  449.  
  450.      :SYM
  451.      .text(001B)
  452.      001B:00401000 WinMain
  453.      001B:004010B5 WndProc
  454.      001B:004011DB CreateProc
  455.      001B:00401270 CommandProc
  456.      001B:00401496 PaintProc
  457.      001B:004014D2 DestroyProc
  458.      001B:004014EA lRandom
  459.      001B:00401530 CreateBounceWindow
  460.      001B:004015A4 BounceProc
  461.      001B:004016A6 BounceCreateProc
  462.      001B:00401787 BounceCommandProc
  463.      001B:0040179C BouncePaintProc
  464.  
  465.      This list of symbol names is from the .text section of the executable.
  466.      The .text section is typically used for procedures and functions. The
  467.      symbols displayed in this example are all functions of GDIDEMO.
  468.  
  469. Setting a Conditional Breakpoint
  470.  
  471.      One of the symbols defined for the GDIDEMO application is the
  472.      LockWindowInfo function. The purpose of this routine is to retrieve a
  473.      pointer value that is specific to a particular instance of a window.
  474.      To learn about conditional and memory breakpoints, you will perform
  475.      the following steps:
  476.  
  477.    * Set a BPX breakpoint on the LockWindowInfo function.
  478.  
  479.    * Edit the breakpoint to use a conditional expression, thus setting a
  480.      conditional breakpoint.
  481.  
  482.    * Set a memory breakpoint to monitor access to a key piece of
  483.      information, as described in Setting a Read-Write Memory Breakpoint on
  484.      page 39.
  485.  
  486. Setting a BPX Breakpoint
  487.  
  488.      Before setting the conditional breakpoint, you need to set a BPX-style
  489.      breakpoint on LockWindowInfo.
  490.  
  491.      1. Set a BPX-style breakpoint on the LockWindowInfo function:
  492.  
  493.      :BPX LockWindowInfo
  494.  
  495.      When one of the GDIDEMO windows needs to draw information in its
  496.      client area, it calls the LockWindowInfo function. Every time the
  497.      LockWindowInfo function is called, SoftICE pops up to let you debug
  498.      the function. The GDIDEMO windows continually updates, so this
  499.      breakpoint goes off quite frequently.
  500.  
  501.      2. Use the BL command to verify that the breakpoint is set.
  502.  
  503.      3. Use either the X or G command to exit SoftICE. SoftICE should pop
  504.      up almost immediately on the LockWindowInfo function.
  505.  
  506. Editing a Breakpoint
  507.  
  508.      From the LockWindowInfo function prototype on source line 47, you can
  509.      see that the function accepts one parameter of type HWND and returns a
  510.      void pointer type. The HWND parameter is the handle to the window that
  511.      is attempting to draw information within its client area. At this
  512.      point, you want to modify the existing breakpoint, adding a
  513.      conditional breakpoint to isolate a specific HWND value.
  514.  
  515.      1. Before you can set the conditional expression, you need to obtain
  516.      the HWND value for the POLYDEMO window. The HWND command provides
  517.      information about application windows. Use the HWND command and
  518.      specify the GDIDEMO process:
  519.  
  520.      :HWND GDIDEMO
  521.  
  522.      The following example illustrates what you should see if you are using
  523.      Windows NT. If you are using Windows 95, your output will vary.
  524.  
  525.      Handle  Class       WinProc   TID Module
  526.      07019C  GDIDEMO     004010B5  2D  GDIDEMO
  527.      100160  MDIClient   77E7F2F5  2D  GDIDEMO
  528.      09017E  BOUNCEDEMO  004015A4  2D  GDIDEMO
  529.      100172  POLYDEMO    00402F34  2D  GDIDEMO
  530.      11015C  DRAWDEMO    00403CE4  2D  GDIDEMO
  531.  
  532.      The POLYDEMO window handle is bold and underlined. This is the window
  533.      handle you want to use to form a conditional expression. If the
  534.      POLYDEMO window does not appear in the HWND output, exit SoftICE using
  535.      the G or X commands (F5) and repeat Step 1 until the window is
  536.      created.
  537.  
  538.      The value used in this example is probably not the same value that
  539.      appears in your output. For the exercise to work correctly, you must
  540.      use the HWND command to obtain the actual HWND value on your system.
  541.  
  542.      Using the POLYDEMO window handle, you can set a conditional expression
  543.      to monitor calls to LockWindowInfo looking for a matching handle
  544.      value. When the LockWindowInfo function is called with the POLYDEMO
  545.      window handle, SoftICE pops up.
  546.  
  547.      2. Because you already have a breakpoint set on LockWindowInfo, use
  548.      the BPE command (Breakpoint Edit) to modify the existing breakpoint:
  549.  
  550.      :BPE 0
  551.  
  552.      When you use the BPE command to modify an existing breakpoint, SoftICE
  553.      places the definition of that breakpoint onto the command line so that
  554.      it can be easily edited. The output of the BPE command appears:
  555.  
  556.      :BPX LockWindowInfo
  557.  
  558.      The cursor appears at the end of the command line and is ready for you
  559.      to type in the conditional expression.
  560.  
  561.      3. Remember to substitute the POLYDEMO window handle value that you
  562.      found using the HWND command instead of the value (100172) used in
  563.      this example. Your conditional expression should appear similar to the
  564.      following example. The conditional expression appears in bold type.
  565.  
  566.      :BPX LockWindowInfo IF ESP->4 == 100172
  567.  
  568.      Note: Win32 applications pass parameters on the stack and at the entry
  569.      point of a function; the first parameter has a positive offset of 4
  570.      from the ESP register. Using the SoftICE expression evaluator, this is
  571.      expressed in the following form: ESP->4. ESP is the CPU stack pointer
  572.      register and the "->" operator causes the lefthand side of the
  573.      expression (ESP) to be indirected at the offset specified on the
  574.      righthand side of the expression (4). For more information on the
  575.      SoftICE expression evaluator refer to Chapter 8: Using Expressions on
  576.      page 125 and for referencing the stack in conditional expressions
  577.      refer to Conditional Breakpoints on page 114.
  578.  
  579.      4. Verify that the breakpoint and conditional expression are correctly
  580.      set by using the BL command.
  581.  
  582.      5. Exit SoftICE using the G or X command (F5).
  583.  
  584.      When SoftICE pops up, the conditional expression will be TRUE.
  585.  
  586. Setting a Read-Write Memory Breakpoint
  587.  
  588.      We set the original breakpoint and subsequently the conditional
  589.      expression so that we could obtain the address of a data structure
  590.      specific to this instance of the POLYDEMO window. This value is stored
  591.      in the windowÆs extra data and is a global handle. The LockWindowInfo
  592.      function retrieves this global handle and uses the Win32 API LocalLock
  593.      to translate it into a pointer that can be used to access the windowÆs
  594.      instance data.
  595.  
  596.      1. Obtain the pointer value for the windows instance data by executing
  597.      up to the return statement on source line 57:
  598.  
  599.      :G .57
  600.  
  601.      2. Win32 API functions return 32-bit values in the EAX register, so
  602.      you can use the BPMD command and specify the EAX register to set a
  603.      memory breakpoint on the instance data pointer.
  604.  
  605.      :BPMD EAX
  606.  
  607.      The BPMD command uses the hardware debug registers provided by Intel
  608.      CPUs to monitor reads and writes to the Dword value at a linear
  609.      address. In this case, you are using BPMD to trap read and write
  610.      accesses to the first Dword of the window instance data.
  611.  
  612.      3. Use the BL command to verify that the memory breakpoint is set.
  613.      Your output should look similar to the following:
  614.  
  615.      :BL
  616.      00) BPX LockWindowInfo IF ((ESP->4)==0x100172)
  617.      01) BPMD #0023:001421F8 RW DR3
  618.  
  619.      Breakpoint index 0 is the execution breakpoint on LockWindowInfo and
  620.      breakpoint index 1 is the BPMD on the window instance data.
  621.  
  622.      4. Use the BD command to disable the breakpoint on the LockWindowInfo.
  623.  
  624.      :BD 0
  625.  
  626.      SoftICE provides the BC (breakpoint clear) and BD (breakpoint disable)
  627.      commands to clear or disable a breakpoint. Disabling a breakpoint is
  628.      useful if you want to re-enable the breakpoint later in your debugging
  629.      session. If you are not interested in using the breakpoint again, then
  630.      it makes more sense to clear it.
  631.  
  632.      5. Use the BL command to verify that the breakpoint on LockWindowInfo
  633.      is disabled. SoftICE indicates that a breakpoint is disabled by
  634.      placing an asterisk (*) after the breakpoint index. Your output should
  635.      appear similar to the following:
  636.  
  637.      :BL
  638.      00) * BPX _LockWindowInfo IF ((ESP->4)==0x100172)
  639.      01) BPMD #0023:001421F8 RW DR3
  640.  
  641.      Note: You can use the BE command to re-enable a breakpoint:
  642.  
  643.      :BE breakpoint-index-number
  644.  
  645.      6. Exit SoftICE using the G or X command. When the POLYDEMO window
  646.      accesses the first Dword of its window instance data, the breakpoint
  647.      triggers and SoftICE pops up.
  648.  
  649.      When SoftICE pops up due to the memory breakpoint, you are in the
  650.      PolyRedraw or PolyDrawBez function. Both functions access the
  651.      nBezTotal field at offset 0 of the POLYDRAW window instance data.
  652.  
  653.      Note: The Intel CPU architecture defines memory breakpoints as traps,
  654.      which means that the breakpoint triggers after the memory has been
  655.      accessed. In SoftICE, the instruction or source line that is
  656.      highlighted is the one after the instruction or source line that
  657.      accessed the memory.
  658.  
  659.      7. Clear the breakpoints you set in this section by using the BC
  660.      command:
  661.  
  662.      :BC *
  663.  
  664.      Note: You can use the wildcard character (*) with the BC, BD, and BE
  665.      commands to clear, disable, and enable all breakpoints.
  666.  
  667.      8. Exit SoftICE using the G or X command.
  668.  
  669.      The operating system terminates the application.
  670.  
  671.      Congratulations on completing your first SoftICE debugging session. In
  672.      this session, you traced through source code, viewed locals and
  673.      structures, and set point-and-shoot, conditional, and read-write
  674.      memory breakpoints. SoftICE provides many more advanced features. The
  675.      SoftICE commands ADDR, HEAP, LOCALS, QUERY, THREAD, TYPES, WATCH, and
  676.      WHAT are just a few of the many SoftICE commands that help you debug
  677.      smarter and faster. Refer to the SoftICE Command Reference for a
  678.      complete explanation of all the SoftICE commands.
  679.